package com.easyfun.healthmagicbox.sync;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.json.JSONException;

import android.content.Context;
import android.util.Log;

import com.easyfun.healthmagicbox.base.DatabaseAccess;
import com.easyfun.healthmagicbox.base.DatabaseAccessImplementation;
import com.easyfun.healthmagicbox.comm.AlarmClockDownloadTask;
import com.easyfun.healthmagicbox.comm.HealthInputDataDownloadTask;
import com.easyfun.healthmagicbox.comm.HealthThreadPool;
import com.easyfun.healthmagicbox.comm.PersonProfileDownloadTask;
import com.easyfun.healthmagicbox.comm.PersonQuestionsDownloadTask;
import com.easyfun.healthmagicbox.comm.PicturesDownloadTask;
import com.easyfun.healthmagicbox.comm.ReferenceDataDescriptionDownloadTask;
import com.easyfun.healthmagicbox.comm.ServerHeartbeatTask;
import com.easyfun.healthmagicbox.comm.SuggestionDownloadTask;
import com.easyfun.healthmagicbox.comm.UserLoginTask;
import com.easyfun.healthmagicbox.comm.UserToPersonsDownloadTask;
import com.easyfun.healthmagicbox.comm.json.ServerHeartBeatListJsonWrapper;
import com.easyfun.healthmagicbox.ormlite.DatabaseHelper;
import com.easyfun.healthmagicbox.ormlite.ServerResponseCode;
import com.easyfun.healthmagicbox.pojo.AlarmClock;
import com.easyfun.healthmagicbox.pojo.DataReferenceDescription;
import com.easyfun.healthmagicbox.pojo.DoctorAndSuggestion;
import com.easyfun.healthmagicbox.pojo.HealthInputData;
import com.easyfun.healthmagicbox.pojo.HeartBeatMessage;
import com.easyfun.healthmagicbox.pojo.PersonProfile;
import com.easyfun.healthmagicbox.pojo.PersonQuestion;
import com.easyfun.healthmagicbox.pojo.Picture;
import com.easyfun.healthmagicbox.pojo.UserToPersons;
import com.easyfun.healthmagicbox.util.PersonProfileCache;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.stmt.DeleteBuilder;
import com.j256.ormlite.stmt.Where;

public class SyncHeartBeatSender implements DatabaseAccess
{	
	private static final String TAG = SyncHeartBeatSender.class.getSimpleName();
	private static SyncHeartBeatSender instance = null;
	private Context mcontext;
	private Object syncObject = new Integer(1);
	private HealthService mservice;
	
	public static SyncHeartBeatSender getInstance(Context context,HealthService service)
	{
		if (instance == null)
		{
			instance = new SyncHeartBeatSender(context,service);
		}
		return instance;
	}

	private SyncHeartBeatSender(Context context,HealthService service)
	{
		mcontext = context;
		mservice = service;
	}
	
	public int sendHeartBeat() 
	{
		Dao<DoctorAndSuggestion, Integer> suggestionDao;
		List<HeartBeatMessage> hblist = new ArrayList<HeartBeatMessage>();
		try {
			suggestionDao = getHelper(mcontext)
						.getDoctorSuggestionDao();
			Dao<HealthInputData, Integer> inputdao = getHelper(mcontext)
					.getInputDataDao();		
			Dao<PersonQuestion, Integer> questiondao = getHelper(mcontext)
					.getQuestionsDao();
			Dao<Picture, Integer> picturedao = getHelper(mcontext)
					.getPictureDao();
			Dao<AlarmClock, Integer> alarmdao = getHelper(mcontext)
					.getAlarmClockDao();
			Dao<UserToPersons, Integer> utopDao = getHelper(mcontext)
					.getUserToPersonsDao();
			Dao<PersonProfile, Integer> profileDao = getHelper(mcontext)
					.getPersonProfileDao();
			
			Dao<DataReferenceDescription, Integer> referenceDataDao = getHelper(mcontext)
					.getReferenceDataDao();
			
			List<UserToPersons> utopresult = utopDao.queryBuilder()
					.orderBy("id", true).where()
					.eq("username", PersonProfileCache.getInstance(mcontext).getUsername(mcontext)).query();
				
			for (UserToPersons up:utopresult)
			{
				String cpersonalID = up.getPersonID();
				HeartBeatMessage hbm = new HeartBeatMessage(cpersonalID);
				long max = suggestionDao
						.queryRawValue(
						"select max(suggestionsyncid) from DoctorAndSuggestion where personID = ?",
						up.getPersonID());
				hbm.setSuggestionMaxID(String.valueOf(max));	
				
				max = inputdao
						.queryRawValue(
								"select max(syncid) from HealthInputData where personID = ?",
								cpersonalID);
				hbm.setHidMaxID(String.valueOf(max));
				
				max = questiondao
						.queryRawValue(
									"select max(syncid) from PersonQuestion where personID = ?",
									cpersonalID);
				hbm.setQuestionMaxID(String.valueOf(max));
				
				max = picturedao
						.queryRawValue(
								"select max(syncid) from Picture where personID = ?",
								cpersonalID);
				hbm.setPictureMaxID(String.valueOf(max));
				//--------------------------------------------------------
				List<AlarmClock> list = alarmdao
						.queryForEq("personID", cpersonalID);
				if (list.size() == 0) {
					hbm.setAlarmMaxID1("-1");
					hbm.setAlarmMaxID2("-1");
				} else if (list.size() == 1) {
					hbm.setAlarmMaxID1( list.get(0).getSyncid()==null?"0":list.get(0).getSyncid());
					hbm.setAlarmMaxID2("-1");
				} else {
					hbm.setAlarmMaxID1( list.get(0).getSyncid()==null?"0":list.get(0).getSyncid());
					hbm.setAlarmMaxID2( list.get(1).getSyncid()==null?"0":list.get(1).getSyncid());
				}
				//--------------------------------------------------------
				String idmodified = up.getServerID()+":"+up.getModified();
				hbm.setUtopIDModifiedDate(idmodified);
				hbm.setUsername(PersonProfileCache.getInstance(mcontext).getUsername(mcontext));
				
				List<PersonProfile> pplist = profileDao.queryForEq("personID", cpersonalID);
				if (pplist.size()==1)
				{
					String profilemodified = pplist.get(0).getModified();
					hbm.setProfileModifiedDate(profilemodified);
				}else
				{
					hbm.setProfileModifiedDate("zzz");
				}
				/*
				HeartBeatMessage hbm = new HeartBeatMessage("-1");
				long maxReferenceDataID = referenceDataDao.queryRawValue("select max(syncid) from DataReferenceDescription");
				hbm.setReferenceDataMaxID(String.valueOf(maxReferenceDataID));
				*/
				hblist.add(hbm);
			}
			
			
			
		} catch (SQLException e1) {
			Log.e(TAG, "heartbeat failed. "+e1.getMessage());
			e1.printStackTrace();
		}
		BasicCommCallback callback = new BasicCommCallback();
		ServerHeartbeatTask hbtask = new ServerHeartbeatTask(mcontext,callback,
				hblist);
		//---------------------------------------------------
		//direct run it
		hbtask.run();
		String responseValue = "";
		int i = 0;
		ServerResponseCode src = callback.getCommResult(ServerHeartbeatTask.class,
				responseValue);
		while ((src == ServerResponseCode.WAITING) && (i < 200)) {
			synchronized (callback) {
				try {
					callback.wait(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			src = callback.getCommResult(ServerHeartbeatTask.class, responseValue);
			i++;
		}
		//---------------------------------------------------
		if ((callback.result == ServerResponseCode.SUCCESS) && 
				(callback.getResultValue().length()>0))
		{
			String latestIDs = callback.getResultValue();
			try {
				ServerHeartBeatListJsonWrapper<?> wrapper = ServerHeartBeatListJsonWrapper
						.getInstance(latestIDs,ServerHeartBeatListJsonWrapper.class);
				List<HeartBeatMessage> hblistresult = wrapper.getMpps();
				compareAndUpdate(hblistresult);
				return 1;
				
			} catch (JSONException e) {
				Log.e(TAG, "heartbeat failed. "+e.toString());
				e.printStackTrace();
			} catch (InstantiationException e) {
				Log.e(TAG, "heartbeat failed. "+e.toString());
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				Log.e(TAG, "heartbeat failed. "+e.toString());
				e.printStackTrace();
			}
			
		}else if (callback.result == ServerResponseCode.NOMORE)
		{
			Log.e(TAG, "no more update from heartbeat");
		}else
		{
			Log.e(TAG, "heartbeat failed");
		}
		return 0;
	}
	
	void compareAndUpdate(List<HeartBeatMessage> thelatest)
	{
		for (HeartBeatMessage hbm: thelatest)
		{
			if ((hbm.getPictureMaxID()!=null) &&
				(hbm.getPictureMaxID().length() > 0))
			{
				downloadPictures(mcontext, hbm.getPersonID());
				mservice.displayNotificationMessage("收到新的照片", true);
			}
			
			if ((hbm.getHidMaxID()!=null) &&
					(hbm.getHidMaxID().length() > 0))
			{
				downloadLatestHID(mcontext, hbm.getPersonID());
				mservice.displayNotificationMessage("收到健康数据", true);
			}
			
			if ((hbm.getQuestionMaxID()!=null) &&
					(hbm.getQuestionMaxID().length() > 0))
			{
				downloadQuestions(mcontext, hbm.getPersonID());
				mservice.displayNotificationMessage("收到新的问题", true);
			}
			
			if ((hbm.getSuggestionMaxID()!=null) &&
					(hbm.getSuggestionMaxID().length() > 0))
			{
				downloadLatestSuggestion(mcontext, hbm.getPersonID());
				mservice.displayNotificationMessage("收到健康顾问的建议", true);
			}
			
			if (((hbm.getAlarmMaxID1()!=null) &&
					(hbm.getAlarmMaxID1().length() > 0)) ||
				((hbm.getAlarmMaxID2()!=null) &&
						(hbm.getAlarmMaxID2().length() > 0)))
			{
				downloadAlarms(mcontext, hbm.getPersonID());
				mservice.displayNotificationMessage("收到新的闹钟提醒", true);
			}
			
			if ((hbm.getUtopIDModifiedDate()!=null) &&
					(hbm.getUtopIDModifiedDate().length() > 0))
			{
				syncPersonProfiles();
				mservice.displayNotificationMessage("收到新的分享人", true);
			}
			
			if ((hbm.getProfileModifiedDate()!=null) &&
					(hbm.getProfileModifiedDate().length() > 0))
			{
				downloadPersonProfile(mcontext, hbm.getPersonID());
				mservice.displayNotificationMessage("收到新的分享人", true);
			}
			/*
			if((hbm.getReferenceDataMaxID() != null)&&
					(hbm.getReferenceDataMaxID().length() > 0))
			{
				downloadReferenceData(mcontext);
				mservice.displayNotificationMessage("收到新的参考数据",true);
			}
			*/
		}
	}
	
	private ServerResponseCode downloadReferenceData(Context context) {
		//Sync suggestions-------------------------------------
				CommCallback callback = new BasicCommCallback();
				ReferenceDataDescriptionDownloadTask task = new ReferenceDataDescriptionDownloadTask(context,callback);
				HealthThreadPool.getInstance().execute(task);
				
				int i = 0;
				while ((callback.getCommResult(null, null) == ServerResponseCode.WAITING) 
						&& (i <5)) { //
					synchronized (syncObject ) {
						try {
							syncObject.wait(1000);
						} catch (InterruptedException e) {
							Log.e(TAG,e.toString());
							e.printStackTrace();
						}
					}
					i++;
				}
				return callback.getCommResult(null, null);
	}
	
	
	
	private ServerResponseCode downloadPersonProfile(Context context,String personID) {
		//Sync suggestions-------------------------------------
		CommCallback callback = new BasicCommCallback();
		PersonProfileDownloadTask task = new PersonProfileDownloadTask(
				personID, 
				context,callback);
		HealthThreadPool.getInstance().execute(task);
		
		int i = 0;
		while ((callback.getCommResult(null, null) == ServerResponseCode.WAITING) 
				&& (i <5)) { //
			synchronized (syncObject ) {
				try {
					syncObject.wait(1000);
				} catch (InterruptedException e) {
					Log.e(TAG,e.toString());
					e.printStackTrace();
				}
			}
			i++;
		}
		return callback.getCommResult(null, null);
		
	}

	protected ServerResponseCode downloadLatestHID(Context context, String personID)
	{
		CommCallback callback2 = new BasicCommCallback();
		HealthInputDataDownloadTask hidtask = new HealthInputDataDownloadTask(
				context, 
				personID, 
				callback2);
		HealthThreadPool.getInstance().execute(hidtask);
		int i = 0;
		while ((callback2.getCommResult(null, null) == ServerResponseCode.WAITING) 
				&& (i <5)) { //
			synchronized (syncObject) {
				try {
					syncObject.wait(1000);
				} catch (InterruptedException e) {
					Log.e(TAG,e.toString());
					e.printStackTrace();
				}
			}
			i++;
		}
		return callback2.getCommResult(null, null);
	}
	
	protected ServerResponseCode downloadLatestSuggestion(Context context,String personID)
	{
		//Sync suggestions-------------------------------------
		CommCallback callback = new BasicCommCallback();
		SuggestionDownloadTask task = new SuggestionDownloadTask(
				context, 
				personID, 
				callback);
		HealthThreadPool.getInstance().execute(task);
		
		int i = 0;
		while ((callback.getCommResult(null, null) == ServerResponseCode.WAITING) 
				&& (i <5)) { //
			synchronized (syncObject ) {
				try {
					syncObject.wait(1000);
				} catch (InterruptedException e) {
					Log.e(TAG,e.toString());
					e.printStackTrace();
				}
			}
			i++;
		}
		return callback.getCommResult(null, null);
	}
	
	protected ServerResponseCode downloadQuestions(Context context, String personID)
	{
		CommCallback callback2 = new BasicCommCallback();
		PersonQuestionsDownloadTask task = new PersonQuestionsDownloadTask( 
				context,
				personID, 
				callback2);
		HealthThreadPool.getInstance().execute(task);
		
		int i = 0;
		while ((callback2.getCommResult(null, null) == ServerResponseCode.WAITING) 
				&& (i <5)) { //
			synchronized (syncObject) {
				try {
					syncObject.wait(1000);
				} catch (InterruptedException e) {
					Log.e(TAG,e.toString());
					e.printStackTrace();
				}
			}
			i++;
		}
		return callback2.getCommResult(null, null);
	}
	

	protected ServerResponseCode downloadPictures(Context context,String personID)
	{
		//Sync suggestions-------------------------------------
		CommCallback callback = new BasicCommCallback();
		PicturesDownloadTask task = new PicturesDownloadTask(
				context, 
				personID, 
				callback);
		HealthThreadPool.getInstance().execute(task);
		
		int i = 0;
		while ((callback.getCommResult(null, null) == ServerResponseCode.WAITING) 
				&& (i <5)) { //
			synchronized (syncObject) {
				try {
					syncObject.wait(1000);
				} catch (InterruptedException e) {
					Log.e(TAG,e.toString());
					e.printStackTrace();
				}
			}
			i++;
		}
		return callback.getCommResult(null, null);
	}
	

	private ServerResponseCode downloadAlarms(Context context,
			String personID) {
		//Sync suggestions-------------------------------------
				CommCallback callback = new BasicCommCallback();
				AlarmClockDownloadTask task = new AlarmClockDownloadTask(
						context, 
						personID, 
						callback);
				HealthThreadPool.getInstance().execute(task);
				
				int i = 0;
				while ((callback.getCommResult(null, null) == ServerResponseCode.WAITING) 
						&& (i <5)) { //
					synchronized (syncObject) {
						try {
							syncObject.wait(1000);
						} catch (InterruptedException e) {
							Log.e(TAG,e.toString());
							e.printStackTrace();
						}
					}
					i++;
				}
				return callback.getCommResult(null, null);
	}

	private void syncPersonProfiles()
	{
		CommCallback callback3 = new BasicCommCallback();
		UserToPersonsDownloadTask utoptask = new UserToPersonsDownloadTask(
				PersonProfileCache.getInstance(mservice).getUsername(mservice), 
				mservice,
				callback3);
		HealthThreadPool.getInstance().execute(utoptask);
		int i = 0;
		while ((callback3.getCommResult(null, null) == ServerResponseCode.WAITING) 
				&& (i <5)) { //
			synchronized (syncObject) {
				try {
					syncObject.wait(1000);
				} catch (InterruptedException e) {
					Log.e(TAG,e.toString());
					e.printStackTrace();
				}
			}
			i++;
		}
		
		if (callback3.getCommResult(null, null) == ServerResponseCode.SUCCESS)
		{
			//service.displayNotificationMessage("收到新的健康数据", true);
		}
	}
	
	@Override
	public DatabaseHelper getHelper(Context context) {
		return DatabaseAccessImplementation.getInstance().getHelper(context);
	}
	
}
